package com.hsmw.api.service;

import com.alibaba.fastjson.JSONObject;
import com.htn.common.core.base.DataResponse;
import org.apache.http.Header;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class HttpAPIUtils {
    //  客户端从服务端读取数据的超时时间
    private static final int HTTP_TIMEOUT = 500;
    //  客户端与服务器建立连接的超时时间
    private static final int HTTP_CON_TIMEOUT = 200;
    //  客户端从连接池中获取连接的超时时间
    private static final int HTTP_CON_REQ_TIMEOUT = 100;
    //  路由的默认最大连接
    private static final int HTTP_MAX_PERROUTE = 500;
    //  整个连接池连接的最大值
    private static final int HTTP_MAX_TOTAL = 1000;
    private static RequestConfig defaultRequestConfig = null;
    private static CloseableHttpClient httpClient = null;

    static {
        //  创建连接池管理器
        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
        //  设置socket配置
        SocketConfig socketConfig = SocketConfig.custom()
                .setTcpNoDelay(true)
                .build();
        connManager.setDefaultSocketConfig(socketConfig);
        connManager.setMaxTotal(HTTP_MAX_TOTAL);
        connManager.setDefaultMaxPerRoute(HTTP_MAX_PERROUTE);
        //  设置获取连接超时时间、建立连接超时时间、从服务端读取数据的超时时间
        defaultRequestConfig = RequestConfig.custom()
                .setSocketTimeout(HTTP_TIMEOUT)
                .setConnectTimeout(HTTP_CON_TIMEOUT)
                .setConnectionRequestTimeout(HTTP_CON_REQ_TIMEOUT)
                .build();
        //  创建httpclient实例
        httpClient = HttpClients.custom()
                .setConnectionManager(connManager)
                .setDefaultRequestConfig(defaultRequestConfig)
                .build();
    }

    /**
     * 不带参数的get请求，如果状态码为200，则返回body，如果不为200，则返回null
     *
     * @param url
     * @return
     * @throws Exception
     */

    public static String doGet(String url) throws Exception {
        // 声明 http get 请求
        HttpGet httpGet = new HttpGet(url);

        // 装载配置信息
        httpGet.setConfig(defaultRequestConfig);

        // 发起请求
        CloseableHttpResponse response = httpClient.execute(httpGet);

        // 判断状态码是否为200
        if (response.getStatusLine().getStatusCode() == 200) {
            // 返回响应体的内容
            return EntityUtils.toString(response.getEntity(), "UTF-8");
        }
        return null;
    }

    /**
     * 带参数的get请求，如果状态码为200，则返回body，如果不为200，则返回null
     *
     * @param url
     * @return
     * @throws Exception
     */

    public static String doGet(String url, Map<String, Object> map) throws Exception {
        URIBuilder uriBuilder = new URIBuilder(url);

        if (map != null) {
            // 遍历map,拼接请求参数
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                uriBuilder.setParameter(entry.getKey(), entry.getValue().toString());
            }
        }

        // 调用不带参数的get请求
        return doGet(uriBuilder.build().toString());

    }



/**
     * 带参数的post请求
     *
     * @param url
     * @param map
     * @return
     * @throws Exception
     */

    public static String doPost(String url, Map<String, Object> map) throws Exception {
        // 声明httpPost请求
        HttpPost httpPost = new HttpPost(url);
        // 加入配置信息
        httpPost.setConfig(defaultRequestConfig);

        // 判断map是否为空，不为空则进行遍历，封装from表单对象
        if (map != null) {
            List<NameValuePair> list = new ArrayList<NameValuePair>();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                list.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
            }
            // 构造from表单对象
            UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(list, "UTF-8");

            // 把表单放到post里
            httpPost.setEntity(urlEncodedFormEntity);
        }

        // 发起请求
        CloseableHttpResponse response = httpClient.execute(httpPost);
        return  EntityUtils.toString(response.getEntity(), "UTF-8");
    }


    /**
     * 带参数的post请求
     *
     * @param url
     * @param map
     * @return
     * @throws Exception
     */

    public static String doPost(String url, JSONObject map) throws Exception {
        // 声明httpPost请求
        HttpPost httpPost = new HttpPost(url);
        // 加入配置信息
        httpPost.setConfig(defaultRequestConfig);
        httpPost.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);


        // 判断map是否为空，不为空则进行遍历，封装from表单对象
        if (map != null) {

            StringEntity s = new StringEntity(map.toString());
            s.setContentEncoding("utf-8");
            s.setContentType("application/json");//发送json数据需要设置contentType
            httpPost.setEntity(s);
        }

        // 发起请求
        CloseableHttpResponse response = httpClient.execute(httpPost);
        return  EntityUtils.toString(response.getEntity(), "UTF-8");
    }
/**
     * 不带参数post请求
     *
     * @param url
     * @return
     * @throws Exception
     */

    public static String doPost(String url) throws Exception {
        return doPost(url, null);
    }


/**
     * 通过post方式调用http接口
     * @param url     url路径

     * @return
     * @throws Exception
     */
        public  static String HttpPostWithJson(String url, String json) {
            String returnValue = "这是默认返回值，接口调用失败";
            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            try{
                //第一步：创建HttpClient对象
                httpClient = HttpClients.createDefault();

                //第二步：创建httpPost对象
                HttpPost httpPost = new HttpPost(url);

                //第三步：给httpPost设置JSON格式的参数
                StringEntity requestEntity = new StringEntity(json,"utf-8");
                requestEntity.setContentEncoding("UTF-8");
                httpPost.setHeader("Content-type", "application/json");
                httpPost.setEntity(requestEntity);

                //第四步：发送HttpPost请求，获取返回值
                returnValue = httpClient.execute(httpPost,responseHandler); //调接口获取返回值时，必须用此方法

            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
            finally {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            //第五步：处理返回值
            return returnValue;
        }
}
